package com.example.mqtt.server.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MqttServer {
    /**
     * bossGroup和workerGroup是两个线程池, 它们默认线程数为CPU核心数乘以2
     * bossGroup用于接收客户端传过来的请求，接收到请求后将后续操作交由workerGroup处理
     */
    private NioEventLoopGroup bossGroup;

    private NioEventLoopGroup workGroup;

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    /**
     * 启动服务
     */
    public void startup(int port) {
        try {
            bossGroup = new NioEventLoopGroup();
            workGroup = new NioEventLoopGroup();

            // 服务端启动辅助类
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workGroup);

            // 指定服务器端监听套接字通道NioServerSocketChannel，其内部管理了一个Java NIO中的ServerSocketChannel实例。
            bootstrap.channel(NioServerSocketChannel.class);

            // 等待队列
            bootstrap.option(ChannelOption.SO_REUSEADDR, true).option(ChannelOption.SO_BACKLOG, 1024).option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT).option(ChannelOption.SO_RCVBUF, 10485760);

            bootstrap.childOption(ChannelOption.TCP_NODELAY, true).childOption(ChannelOption.SO_KEEPALIVE, true).childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);

            // 设置业务职责链，责任链具体是什么？
            // 它其实就是由一个个的ChannelHandler串联而成，形成的链式结构。正是这一个个的ChannelHandler帮我们完成了要处理的事情。
            bootstrap.childHandler(new MqttChannelInitializer());

            // 执行端口绑定，sync方法用于阻塞当前Thread，直到端口绑定操作完成
            bootstrap.bind(port).addListener(future -> log.info("服务端成功绑定端口号={}", port));

        } catch (Exception e) {
            // 优雅退出，释放线程池资源
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
            log.error("start exception", e);
        }
    }
}
